/* This file is part of REWise.
 *
 * REWise is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * REWise is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 */

#ifndef H_REWISE_INFLATE
#define H_REWISE_INFLATE

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>

#include "crc32.h"
#include "reader.h"

#define HUFFMAN_LEFT  0
#define HUFFMAN_RIGHT 1

// DEFLATE block types
#define BTYPE_UNCOMPRESSED 0x00  // https://www.rfc-editor.org/rfc/rfc1951#page-11
#define BTYPE_FIXED        0x01  // https://www.rfc-editor.org/rfc/rfc1951#page-12
#define BTYPE_DYNAMIC      0x02  // https://www.rfc-editor.org/rfc/rfc1951#page-13

// DELFATE sliding window size and chunk size
#define WINDOW_SIZE        0x8000  // 32K https://www.rfc-editor.org/rfc/rfc1951#page-4
#define CHUNK_SIZE         0x4000  // 16K


typedef struct __HuffmanNode HuffmanNode;

struct __HuffmanNode {
  int value;
  HuffmanNode * childeren[2];
  bool leafes[2];
};


typedef struct {
  unsigned char bitBuff;
  unsigned char window[WINDOW_SIZE];
  unsigned char chunkBuff[CHUNK_SIZE];
  uint8_t bitOffset;
  uint32_t windowPosition;
  uint32_t chunkBuffPosition;
  uint32_t chunkBuffSize;
  FILE * inputFile;
  FILE * outputFile;     // Valid open FILE or NULL to not output to file.
  long inputFileSize;
  long outputSize;       // Current output size in bytes (inflateWriteOutput()
                         // will update this).
  long wantedOutputSize; // Wanted output size in bytes (should be defined pre
                         // inflation), this value will be from the
                         // WiseScript.bin or set to -1 to be ignored.
  uint32_t crc32;
  long deflatedStart;    // TODO tmp for debugging
} InflateObject;


bool huffmanInitFixedTrees(void);
void huffmanFreeFixedTrees(void);
void inflateInit(InflateObject * inflateObj, FILE * inputFile);
void inflateNew(InflateObject * inflateObj, FILE * outputFile,
                long wantedOutputSize);

bool inflateNext(InflateObject * inflateObj);
bool inflateExtractNextFile(InflateObject * inflateObj,
                            const char * outputFilePath,
                            long wantedOutputSize);

// only used to generate the lookup table
#ifdef REWISE_DEV_DEBUG
void inflateInitStaticTables(void);
void inflatePrintStaticTables(void);
#endif

#endif
